//
//  StatusDAL.swift
//  sinaWeibo
//
//  Created by liii on 16/9/2.
//  Copyright © 2016年 liii. All rights reserved.
//

import UIKit

class StatusDAL: NSObject {

    //1 检测本地是否有缓存数据
    class func loadHomeData(max_id: Int64, since_id: Int64 = 0, finished: (array: [[String : AnyObject]]?) -> ()) {
    
        // 用户过期判断
        guard let token = sharedUser.access_token else {
            print("用户未登陆, 或者token已过期")
            finished(array: nil)
            return
        }
        
        // 检查本地缓存, 没有缓存数据
        guard let res = checkoutCacheStatus(max_id, since_id: since_id) else {
            
            // 参数部分
            let urlString = "2/statuses/home_timeline.json"
            var parameters = ["access_token" : token]
            
            // since_id 大于0, 说明不是首次加载, 即用户执行了"下拉刷新", 这时候传递刷新的指定时间以后产生的新微薄数据
            if since_id > 0 {
                parameters["since_id"] = "\(since_id)"
            }
            // since_id 大于0, 说明不是首次加载, 即用户执行了"下拉刷新", 这时候传递刷新的指定时间以后产生的新微薄数据
            if max_id > 0 {
                parameters["max_id"] = "\(max_id)"
            }
            
            //2 如果没有, 就向服务器发送网络请求, 通过回调拿到数据
            HTTPClient.sharedClient.requestJSONDict(.GET, urlString: urlString, parameters: parameters, finished: { (dict, error) -> () in
                
                // 请求失败
                if error != nil {
//                    finished(dict: nil)
                    return
                }
                
                // 请求成功, 字典转模型, 回调数据
                // 获取status字典
                guard let array = dict!["statuses"] as? [[String : AnyObject]] else {
                    print("数据格式错误")
//                    finished(dict: nil)
                    return
                }
                
                // 缓存网络数据到本地数据库
                StatusDAL.saveStatus(array)
                
                // 回调数据
                finished(array: array)
            })
            return
        }
        
        //3 如果有,就直接返回缓存数据
        finished(array: res)
    }
    
    
    
    //4 查询数据(根据id, 从数据库读取数据)
    class func checkoutCacheStatus(max_id: Int64, since_id: Int64 = 0) -> [[String : AnyObject]]? {
        
        // 判断用户是否登陆
        guard let userId = UserAccount.sharedAccount.uid else {
            print("您还未登陆, 请先登陆")
            return nil
        }
        
        // 查询并获取, 某个字段的数据(***注意后边的控股)
        var sql = "SELECT status FROM T_Status WHERE userId = \(userId)\n"
        
        // 下拉刷新, 向上查询
        if since_id > 0 {
            sql += "AND statusId > \(since_id) "
        }
        
        // 上拉刷新, 乡下查询
        if max_id > 0 {
            sql += "AND statusId < \(max_id) "
        }
        
        // 每次最多回去20条
        sql += "ORDER BY statusId DESC LIMIT 20"
        
        print(sql)
        
        // 临时数组
        var arrM: [[String : AnyObject]]?
        // 执行查询语句
        SQLiteManager.sharedManager.queue.inDatabase { (db) -> Void in
            
            // 保证能够从数据库中能, 拿到数据, 输入拿不到, 就推出不再执行
            guard let res = try? db.executeQuery(sql) else {
                return
            }
            
            // 实例化临时数组, 注意在保证数据库有数据的时候再实例化
            arrM = [[String : AnyObject]]()
            
            // 遍历结果集
            while res.next() {
                // 根据字段获取对应值
                let statusData = res.dataForColumn("status")
                // 反序列化(把数据库中的二进制数据, 转换成字典)
                let dict = try! NSJSONSerialization.JSONObjectWithData(statusData, options: [])
                
                // 拼接到数组中
                print(dict)
                arrM?.append(dict as! [String : AnyObject])
            }
        }
        
        return arrM
    }

    //5 插入数据(缓存请求到的网络数据)
    class func saveStatus(array: [[String : AnyObject]]) {
    
        // 判断用户是否登陆
        guard let userId = UserAccount.sharedAccount.uid else {
            print("您还未登陆, 请先登陆")
            return
        }
        
        // 向数据库表中插入数据(当重复插入一个主键的时候, sqlite会保存)
        // T_Status (statusId, status, userId) VALUES(?,?,?);
        // 2016-09-10 15:42:15.766 sinaWeibo[3403:105113] Unknown error finalizing or resetting statement (19: UNIQUE constraint failed: T_Status.statusId)
        // 注意"OR REPLACE"用来防止重复插入某一个数据
        let sql = "INSERT OR REPLACE INTO T_Status (statusId, status, userId) VALUES(?,?,?);"
        
        for status in array {
            // 获取statusId
            let statusId = status["id"] as! NSNumber
            // 把status字典, 转成二进制数据存储(因为数据库中不能直接存储"字典"数据)
            let statusData = try! NSJSONSerialization.dataWithJSONObject(status, options: [])
            
            // 使用"事务"进行sql语句, 把数据插入到数据库中
            SQLiteManager.sharedManager.queue.inTransaction({ (db, rollback) -> Void in
                // 异常处理
                do {
                    // 插入数据
                    try db.executeUpdate(sql, statusId, statusData, userId)
                } catch {
                    // 异常回滚, 提示错误
                    print(error)
                    rollback.memory = true
                }
            })
        }
    }
    
}
